1 O que é MLOps?
A ponte entre protótipo e produção — por que 87% dos projetos de IA nunca chegam lá.
Por que projetos de IA falham em produção?
Modelo degrada
Dados mudam com o tempo, modelo fica obsoleto. Sem monitoramento, você não percebe.
Custos explosivos
LLMs cobram por token. Sem otimização, a conta chega inesperada.
Bugs silenciosos
Modelo responde errado, mas ninguém percebe sem métricas claras.
Deploy manual
Atualizar modelo vira um processo lento e arriscado, feito manualmente.
Os 6 pilares do MLOps
1. Observabilidade
Rastrear cada etapa do pipeline: input, chunks, prompt, output, latência, tokens.
2. Versionamento
Versionar modelos, datasets, prompts e código. Saber exatamente o que está em produção.
3. Monitoramento
Detectar drift (degradação) automaticamente. Alertas antes que usuários percebam.
4. CI/CD
Automatizar testes e deploy. Novo modelo vai para produção com um commit.
5. Otimização de custos
Cache, modelos menores, quantização. Reduzir custos sem perder qualidade.
6. Avaliação contínua
Testar modelo regularmente com golden dataset. Garantir que qualidade se mantém.
2 Observabilidade — rastreando tudo
Se você não pode ver, não pode debugar. Logging detalhado de cada etapa do pipeline.
🎮 Dashboard de observabilidade em tempo real
Veja métricas do sistema RAG da Nimbus Cloud sendo atualizadas em tempo real.
📍 Últimas requisições (tracing)
Ferramentas de observabilidade
| Ferramenta | Tipo | Destaque | Preço |
|---|---|---|---|
| Langfuse | Open-source | Self-hosted, tracing completo, avaliação | Grátis (self) / $59/mês (cloud) |
| Arize Phoenix | Open-source | LLM-specific, visualizações avançadas | Grátis |
| LangSmith | Comercial | Integração nativa com LangChain | Desde $39/mês |
| Helicone | Comercial | Proxy para APIs de LLM, caching | Desde $20/mês |
| Weights & Biases | Comercial | Experiment tracking, MLOps completo | Desde $50/mês |
Exemplo: Tracing com Langfuse
from langfuse import Langfuse import time langfuse = Langfuse( public_key="pk-...", secret_key="sk-...", host="https://cloud.langfuse.com" ) def rag_pipeline(question): # Cria trace principal trace = langfuse.trace( name="rag-query", input=question, metadata={"user_id": "user_123"} ) # 1. Embedding da pergunta with langfuse.span(name="embed-question", trace_id=trace.id) as span: start = time.time() q_embedding = embed(question) span.end(output={"dim": len(q_embedding), "latency_ms": (time.time()-start)*1000}) # 2. Busca vetorial with langfuse.span(name="vector-search", trace_id=trace.id) as span: start = time.time() chunks = vector_db.search(q_embedding, top_k=5) span.end(output={"chunks": len(chunks), "latency_ms": (time.time()-start)*1000}) # 3. Reranking with langfuse.span(name="rerank", trace_id=trace.id) as span: start = time.time() chunks = rerank(question, chunks, top_k=3) span.end(output={"reranked": len(chunks), "latency_ms": (time.time()-start)*1000}) # 4. Geração pelo LLM with langfuse.span(name="llm-generation", trace_id=trace.id) as span: start = time.time() prompt = build_prompt(chunks, question) response = ollama.chat(model="llama3.1:8b", messages=[...]) span.end( output=response, metadata={"tokens": response.usage.total_tokens, "latency_ms": (time.time()-start)*1000} ) # 5. Avaliação automática faithfulness = evaluate_faithfulness(response, chunks) trace.score(name="faithfulness", value=faithfulness) trace.end(output=response) return response # Cada requisição gera um trace completo no Langfuse # Você pode ver: input, chunks recuperados, prompt, output, latências, scores
3 Versionamento — saber o que está em produção
Versionar modelos, datasets, prompts e código. Rollback em 1 clique.
O que versionar?
Modelos
Qual versão do LLM está em produção? Qual adapter LoRA? Qual modelo de embedding?
Datasets
Qual versão do golden dataset foi usada na última avaliação? Quais documentos estão indexados?
Prompts
Qual template de prompt está ativo? Mudanças no prompt podem quebrar tudo.
Código
Qual versão do pipeline RAG está rodando? Git básico para código.
Ferramentas de versionamento
| Ferramenta | O que versiona | Destaque |
|---|---|---|
| MLflow | Modelos, experimentos, métricas | Padrão da indústria, open-source |
| DVC | Datasets, modelos grandes | Git-like para arquivos grandes |
| Promptflow | Prompts, flows | Microsoft, integração com Azure |
| Git | Código, prompts em texto | Básico mas essencial |
| ChromaDB snapshots | Vector DB | Backup do índice vetorial |
Exemplo: Versionamento com MLflow
import mlflow mlflow.set_tracking_uri("http://localhost:5000") mlflow.set_experiment("nimbus-rag") with mlflow.start_run(run_name="v2.3-reranker-bge"): # Log de parâmetros mlflow.log_param("embedding_model", "nomic-embed-text") mlflow.log_param("reranker", "bge-reranker-v2-m3") mlflow.log_param("llm", "llama3.1:8b") mlflow.log_param("chunk_size", 400) mlflow.log_param("top_k", 5) # Log de métricas mlflow.log_metric("faithfulness", 0.92) mlflow.log_metric("answer_relevancy", 0.88) mlflow.log_metric("context_precision", 0.85) mlflow.log_metric("latency_p95", 2.3) # Log do modelo mlflow.sklearn.log_model(reranker, "reranker") # Log do prompt template with open("prompt_template.txt") as f: mlflow.log_text(f.read(), "prompt_template.txt") # Log do dataset de avaliação mlflow.log_artifact("golden_dataset_v2.json") # Registrar modelo como "production" mlflow.register_model("runs:/abc123/reranker", "nimbus-reranker") # Agora você pode: # - Ver histórico de experimentos # - Comparar métricas entre versões # - Fazer rollback para versão anterior # - Saber exatamente o que está em produção
Prompts como código
# Trate prompts como código — versionados no Git # prompts/rag_template_v2.txt SYSTEM_PROMPT = """Você é o Nimbus Assistant. REGRAS: 1. Responda APENAS com base no CONTEXTO. 2. Cite fontes no formato [Fonte: XXX]. 3. Se não souber, diga "Não encontrei". CONTEXTO: {context} PERGUNTA: {question}""" # No código Python: with open("prompts/rag_template_v2.txt") as f: template = f.read() # Mudanças no prompt vão para o Git: # git add prompts/ # git commit -m "feat: add citation requirement to RAG prompt" # git push # Se algo quebrar: # git revert HEAD # → prompt volta para versão anterior em segundos
4 Detecção de Drift — quando o modelo degrada
Modelos não são "treine uma vez, esqueça para sempre". Eles degradam com o tempo.
🎮 Simulador: Monitoramento de drift em tempo real
Veja a métrica de faithfulness do RAG ao longo do tempo. Quando cai abaixo do threshold, um alerta é disparado.
Métrica: Faithfulness (resposta fiel ao contexto)
Ação recomendada: Nenhuma — modelo operando normalmente
Tipos de drift
Data Drift
Distribuição dos inputs muda. Ex: novos tipos de perguntas que o modelo não viu no treino.
Concept Drift
Relação entre input e output muda. Ex: "timeout" antes significava erro, agora significa configuração.
Prompt Drift
LLMs podem mudar comportamento entre versões. Atualizar modelo = risco de drift.
Upstream Drift
Documentos fonte mudam. Ex: nova versão da API, novos processos internos.
Como detectar drift automaticamente
from ragas import evaluate from ragas.metrics import faithfulness, answer_relevancy import pandas as pd # Golden dataset: 100 perguntas com respostas ideais golden_dataset = pd.read_json("golden_dataset_v2.json") def check_drift(): # Roda avaliação no dataset results = evaluate( dataset=golden_dataset, metrics=[faithfulness, answer_relevancy] ) current_faithfulness = results["faithfulness"] current_relevancy = results["answer_relevancy"] # Compara com baseline (versão anterior) baseline = load_baseline() # do MLflow # Calcula degradação faithfulness_drop = baseline.faithfulness - current_faithfulness relevancy_drop = baseline.relevancy - current_relevancy # Alertas if faithfulness_drop > 0.05: send_alert(f"⚠️ Faithfulness caiu {faithfulness_drop:.2f}!") if relevancy_drop > 0.05: send_alert(f"⚠️ Answer relevancy caiu {relevancy_drop:.2f}!") # Log no MLflow mlflow.log_metric("faithfulness", current_faithfulness) mlflow.log_metric("answer_relevancy", current_relevancy) return results # Roda diariamente (cron job) # 0 2 * * * python check_drift.py
O que fazer quando detectar drift?
| Causa | Sintoma | Ação |
|---|---|---|
| Novos tipos de perguntas | Faithfulness cai | Adicionar exemplos ao dataset de treino, fine-tuning |
| Documentos desatualizados | Context precision cai | Reindexar documentos, remover obsoletos |
| Mudança no LLM | Todas as métricas caem | Rollback para versão anterior do modelo |
| Prompt ruim | Answer relevancy cai | Revisar prompt template, A/B testing |
| Embedding desatualizado | Context recall cai | Reindexar com novo modelo de embedding |
5 Avaliação contínua — RAGAS em produção
Provar que seu RAG funciona — não só no demo, mas todo dia.
Métricas do RAGAS
| Métrica | O que mede | Ideal | Como melhorar |
|---|---|---|---|
| Faithfulness | Resposta é fiel ao contexto? (sem alucinação) | > 0.90 | Prompt mais restritivo, temperature baixa |
| Answer Relevancy | Resposta responde a pergunta? | > 0.85 | Melhorar prompt, reranking |
| Context Precision | Chunks certos foram recuperados? | > 0.80 | Busca híbrida, melhor chunking |
| Context Recall | Toda informação necessária foi recuperada? | > 0.80 | Aumentar top-K, melhorar embeddings |
Golden dataset — sua "prova" do RAG
# golden_dataset.json [ { "question": "Qual o timeout padrão do endpoint /v2/sync?", "ground_truth": "O timeout padrão é 30 segundos.", "contexts": ["Docs API v3.2: timeout default 30s"], "category": "technical" }, { "question": "Quais NFs de equipamentos chegaram em junho?", "ground_truth": "NF 12345 da Tech Ltda, R$ 48.500, recebida em 03/06.", "contexts": ["NF 12345 | Tech Ltda | 03/06/2025 | R$48.500"], "category": "financial" }, { "question": "Como aumentar o timeout?", "ground_truth": "Edite config.yaml, adicione NIMBUS_TIMEOUT: 120 e reinicie.", "contexts": ["Runbook RB-018: editar config.yaml..."], "category": "how-to" } // ... 100+ exemplos cobrindo todas as categorias ] # Como construir o golden dataset: # 1. Colete perguntas reais de usuários # 2. Respostas ideais escritas por especialistas # 3. Contextos relevantes (chunks que deveriam ser recuperados) # 4. Categorize por tipo (técnica, financeira, como-fazer, etc.) # 5. Mantenha atualizado — adicione novos casos regularmente
🎮 Simulador: Avaliação RAGAS
Execute uma avaliação simulada no golden dataset
A/B testing de prompts
# Compare dois prompts em produção import random def rag_with_ab_test(question): # 50% prompt A, 50% prompt B variant = "A" if random.random() > 0.5 else "B" if variant == "A": prompt = PROMPT_V1 # versão atual else: prompt = PROMPT_V2 # nova versão response = generate(prompt, question) # Log no Langfuse com variant langfuse.trace( name="rag-query", metadata={"variant": variant}, output=response ) # Depois de 1000 requisições, compare métricas # Langfuse mostra: faithfulness A vs B, latência A vs B, etc. return response # Após 1 semana: # - Variant A: faithfulness 0.89, latência 1.8s # - Variant B: faithfulness 0.93, latência 1.9s # → Promove B para 100% do tráfego
6 CI/CD para IA — automatizando tudo
Do commit ao deploy em produção — sem intervenção manual.
🎮 Pipeline CI/CD interativo
Veja cada etapa do pipeline sendo executada automaticamente após um commit.
GitHub Actions → MLflow → Produção
Exemplo: GitHub Actions para RAG
# .github/workflows/rag-ci.yml name: RAG CI/CD on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | pip install -r requirements.txt pip install ragas pytest - name: Run unit tests run: pytest tests/ - name: Run RAG evaluation run: | python evaluate_rag.py \ --dataset golden_dataset.json \ --output results.json - name: Check metrics threshold run: | python check_metrics.py \ --results results.json \ --min-faithfulness 0.90 \ --min-relevancy 0.85 - name: Upload to MLflow if: success() run: | python log_to_mlflow.py \ --run-name "ci-${{ github.sha }}" \ --results results.json deploy: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Deploy to production run: | curl -X POST ${{ secrets.DEPLOY_WEBHOOK }} \ -H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" - name: Smoke test run: | python smoke_test.py \ --endpoint ${{ secrets.PROD_URL }} \ --question "Qual o timeout do /v2/sync?"
Etapas do pipeline
| Etapa | O que faz | Falha se... |
|---|---|---|
| 1. Testes unitários | Testa funções individuais do pipeline | Algum teste falhar |
| 2. Avaliação RAG | Roda RAGAS no golden dataset | Métricas abaixo do threshold |
| 3. Testes de integração | Testa pipeline completo com dados reais | Timeout, erro de conexão |
| 4. Log no MLflow | Registra experimento e métricas | MLflow indisponível |
| 5. Deploy | Deploy para produção (Docker, K8s) | Falha no deploy |
| 6. Smoke test | Testa endpoint em produção | Resposta errada ou lenta |
| 7. Rollback automático | Se smoke test falhar, volta versão anterior | — |
7 Custos e otimização
LLMs cobram por token. Sem otimização, a conta chega inesperada.
🎮 Calculadora de custos
Estime o custo mensal do seu sistema RAG baseado no uso.
RAG da Nimbus Cloud — Estimativa mensal
Estratégias de otimização
Semantic Cache
Cacheia respostas semanticamente similares. Reduz 30-60% das chamadas ao LLM.
Chunks menores
Menos tokens no prompt = menos custo. Sweet spot: 300-500 tokens.
Reranking
Recupera top-20, rerankeia, passa top-3 ao LLM. Menos tokens, melhor qualidade.
Modelos locais
Llama 3 8B, Mistral 7B rodam em GPU local. Custo marginal = energia elétrica.
Quantização
GGUF 4-bit reduz uso de RAM em 4x. Quase sem perda de qualidade.
Modelos menores para tarefas simples
Classificação com Llama 3 8B, geração complexa com Claude 3 Sonnet.
Exemplo: Semantic Cache
import chromadb from sklearn.metrics.pairwise import cosine_similarity class SemanticCache: def __init__(self, threshold=0.95): self.db = chromadb.Client() self.cache = self.db.get_or_create_collection("semantic_cache") self.threshold = threshold def get(self, question): # Busca pergunta semanticamente similar no cache q_embedding = embed(question) results = self.cache.query( query_embeddings=[q_embedding], n_results=1 ) if results["distances"][0][0] > self.threshold: return results["documents"][0][0] # Cache hit! return None # Cache miss def set(self, question, answer): # Adiciona ao cache q_embedding = embed(question) self.cache.add( embeddings=[q_embedding], documents=[answer], ids=[hash(question)] ) # Uso no pipeline RAG cache = SemanticCache(threshold=0.95) def rag_with_cache(question): # 1. Tenta cache cached = cache.get(question) if cached: log_metric("cache_hit", 1) return cached # Economia de $$$! # 2. Cache miss — roda pipeline normal log_metric("cache_hit", 0) response = rag_pipeline(question) # 3. Salva no cache cache.set(question, response) return response # Com 30% de cache hit rate: # - 1500 req/dia × 30% = 450 req economizadas # - Economia: ~$15/dia = $450/mês
Comparação de custos
| Modelo | Custo/1K req | Qualidade | Latência |
|---|---|---|---|
| GPT-4 Turbo | $3.50 | ⭐⭐⭐⭐⭐ | 2-5s |
| Claude 3 Sonnet | $1.20 | ⭐⭐⭐⭐⭐ | 1-3s |
| GPT-3.5 Turbo | $0.15 | ⭐⭐⭐ | 0.5-1s |
| Llama 3 8B (local) | $0.02 (energia) | ⭐⭐⭐⭐ | 0.5-2s |
| Mistral 7B (local) | $0.02 (energia) | ⭐⭐⭐⭐ | 0.5-2s |
8 Escalabilidade e arquitetura
De 10 para 10.000 requisições por minuto — sem quebrar.
Arquitetura de produção
# Arquitetura escalável para RAG # 1. API Gateway (load balancer) # - Rate limiting # - Autenticação # - Roteamento # 2. Retrieval Service (múltiplas instâncias) # - Embedding da pergunta # - Busca vetorial (ChromaDB/Qdrant) # - Reranking # - Horizontal scaling: Kubernetes replicas # 3. Generation Service (múltiplas instâncias) # - Montagem de prompt # - Chamada ao LLM # - Streaming de resposta # - GPU nodes: A100/H100 para LLMs grandes # 4. Cache Layer (Redis) # - Semantic cache # - Cache de respostas frequentes # - TTL configurável # 5. Vector DB (cluster) # - ChromaDB cluster ou Qdrant cloud # - Sharding por coleção # - Replicas para leitura # 6. Observability Stack # - Langfuse (tracing) # - Prometheus + Grafana (métricas) # - Loki (logs)
🎮 Simulador: Escalabilidade
Como o sistema se comporta sob carga?
Checklist de produção
| Item | Status | Por quê? |
|---|---|---|
| Autenticação (JWT/API keys) | ✅ Obrigatório | Protege contra uso não autorizado |
| Rate limiting | ✅ Obrigatório | Evita abuso e custos explosivos |
| HTTPS/TLS | ✅ Obrigatório | Criptografa dados em trânsito |
| Logs estruturados (JSON) | ✅ Obrigatório | Facilita debug e auditoria |
| Health checks | ✅ Obrigatório | Kubernetes sabe quando restartar |
| Métricas Prometheus | ✅ Recomendado | Grafana dashboards em tempo real |
| Backup do Vector DB | ✅ Recomendado | Recuperação em caso de desastre |
| Multi-region | ⚠️ Opcional | Só se precisar de alta disponibilidade global |
Docker Compose para produção
# docker-compose.prod.yml version: '3.8' services: api: build: . ports: ["8080:8080"] environment: - REDIS_URL=redis://redis:6379 - CHROMA_URL=http://chromadb:8000 - OLLAMA_URL=http://ollama:11434 - LANGFUSE_HOST=http://langfuse:3000 depends_on: [redis, chromadb, ollama, langfuse] deploy: replicas: 3 # 3 instâncias para load balancing resources: limits: cpus: '2' memory: 4G redis: image: redis:7-alpine ports: ["6379:6379"] volumes: ["redis_data:/data"] command: redis-server --appendonly yes chromadb: image: chromadb/chroma:latest ports: ["8000:8000"] volumes: ["chroma_data:/chroma/chroma"] environment: - ANONYMIZED_TELEMETRY=False ollama: image: ollama/ollama:latest ports: ["11434:11434"] deploy: resources: reservations: devices: - capabilities: [gpu] volumes: ["ollama_data:/root/.ollama"] langfuse: image: langfuse/langfuse:2 ports: ["3000:3000"] environment: - DATABASE_URL=postgresql://... - NEXTAUTH_SECRET=... nginx: image: nginx:alpine ports: ["80:80", "443:443"] volumes: - ./nginx.conf:/etc/nginx/nginx.conf - ./certs:/etc/nginx/certs depends_on: [api] volumes: redis_data: chroma_data: ollama_data:
9 Conexão com RAG e próximos passos
Como MLOps completa o ciclo — do protótipo à produção sustentável.
O ciclo completo do RAG em produção
# Ciclo MLOps para RAG # 1. Desenvolvimento (Módulos 0-10) # - Protótipo do RAG # - Fine-tuning do modelo # - Golden dataset criado # 2. Avaliação (Módulo 11) # - RAGAS no golden dataset # - Métricas baseline estabelecidas # - Log no MLflow # 3. Deploy (Módulo 11) # - Docker Compose / Kubernetes # - Langfuse para tracing # - Prometheus para métricas # 4. Monitoramento (Módulo 11) # - Métricas em tempo real # - Detecção de drift # - Alertas automáticos # 5. Melhoria contínua (Módulo 11) # - A/B testing de prompts # - Atualização do golden dataset # - Re-treinamento quando necessário # 6. Responsabilidade (Módulo 12) # - Auditoria de viés # - Conformidade LGPD # - Documentação de impactos
O sistema final da Nimbus Cloud
RAG + Fine-tuning
Modelo especialista do domínio + documentos atualizados em tempo real.
Agents autônomos
Agent decide quando buscar, reformular queries, executar ações.
Multimodal
Processa texto, imagens, áudios e vídeos de forma integrada.
Observabilidade completa
Langfuse + Prometheus + Grafana. Cada requisição rastreada.
CI/CD automatizado
Commit → testes → avaliação → deploy. Sem intervenção manual.
Custos otimizados
Semantic cache + modelos locais + quantização. 80% mais barato.
Checklist final de produção
| Categoria | Item | Status |
|---|---|---|
| Qualidade | Golden dataset atualizado | ✅ |
| Avaliação RAGAS rodando semanalmente | ✅ | |
| Detecção de drift automática | ✅ | |
| Observabilidade | Langfuse configurado | ✅ |
| Métricas Prometheus | ✅ | |
| Alertas automáticos | ✅ | |
| Versionamento | Modelos no MLflow | ✅ |
| Prompts no Git | ✅ | |
| Datasets versionados (DVC) | ✅ | |
| Automação | CI/CD configurado | ✅ |
| Deploy automatizado | ✅ | |
| Rollback automático | ✅ | |
| Custos | Semantic cache ativo | ✅ |
| Modelos locais quando possível | ✅ | |
| Monitoramento de custos | ✅ | |
| Escalabilidade | Load balancing | ✅ |
| Auto-scaling configurado | ✅ | |
| Backups automáticos | ✅ | |
| Segurança | Autenticação (JWT) | ✅ |
| Rate limiting | ✅ | |
| HTTPS/TLS | ✅ |
🎯 Quiz — teste seu conhecimento
Clique em uma alternativa para ver se acertou.
→ O que vem a seguir?
Agora que você sabe colocar IA em produção, vamos explorar a responsabilidade ética.
Conceitos que vamos construir aqui
Viés em IA
Como modelos podem discriminar e como mitigar.
Privacidade
LGPD, proteção de dados, conformidade.
Regulamentação
EU AI Act, Marco Legal da IA no Brasil.
AGI e Futuro
Inteligência Artificial Geral, impacto no trabalho.